﻿#include "LoginAnimationWin.h"
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QBitmap>
#include <QDir>

#include "ConfigWin.h"
#include "RegisterWin.h"
#include "ModifyPwdWin.h"
#include "LoginAccountListWidget.h"
#include "CustomWidget.h"
#include "ClientSocket.h"
#include "unit.h"
#include "Msg.h"
#include "global.h"
#include "DataBaseMagr.h"
#include "MainWindow.h"
#include "CIULog.h"

#define VLine_HEIGHT 330		// 动画效果线条高度;
#define WINDOW_WIDTH 500		// 整个窗口宽度;

LoginAnimationWin::LoginAnimationWin(QWidget *parent)
	: QWidget(parent)
    , m_pMainWin(nullptr)
	, m_isWindowHide(false)
	, m_isPressed(false)
    , m_bConnected(false)
    , m_bLogin(false)
    , m_pClientSocket(new ClientSocket())
{
    ui.setupUi(this);
    this->setAttribute(Qt::WA_DeleteOnClose);
    initWidget();
    initConnections();
    initAnimation();
    initNetWork();
}

void LoginAnimationWin::paintEvent(QPaintEvent *)
{

}

void LoginAnimationWin::initAnimation()
{
    //透明动画
    m_pGraphicsOpacityEffect = new QGraphicsOpacityEffect(ui.widget);
    m_pGraphicsOpacityEffect->setOpacity(0.99);
    ui.widget->setGraphicsEffect(m_pGraphicsOpacityEffect);

    m_pOpacityAnimation = new QPropertyAnimation(m_pGraphicsOpacityEffect,"opacity",ui.widget);
    m_pOpacityAnimation->setDuration(800);
    m_pOpacityAnimation->setStartValue(0.99);
    m_pOpacityAnimation->setEndValue(0.3);

    //窗体移动动画
    m_loginWIndowMoveAnimation = new QPropertyAnimation(ui.widget, "pos");
    m_loginWIndowMoveAnimation->setDuration(800);
    m_loginWIndowMoveAnimation->setStartValue(QPoint(0, 0));
    m_loginWIndowMoveAnimation->setEndValue(QPoint(WINDOW_WIDTH, 0));

    m_pGroupAnimation = new QParallelAnimationGroup(this);
    m_pGroupAnimation->addAnimation(m_pOpacityAnimation);
    m_pGroupAnimation->addAnimation(m_loginWIndowMoveAnimation);
    connect(m_loginWIndowMoveAnimation, &QPropertyAnimation::finished, [=] {
        m_isWindowHide = true;
        ui.widget->setVisible(false);
        m_vLineAnimation->setDirection(QAbstractAnimation::Backward);
        m_vLineAnimation->start();
    });

    // 点击登录按钮动画效果初始化;
    ui.verticalLine->setVisible(false);
    //右侧线条动画
    m_vLineAnimation = new QPropertyAnimation(ui.verticalLine, "minimumHeight");
    m_vLineAnimation->setDuration(400);
    m_vLineAnimation->setStartValue(0);
    m_vLineAnimation->setEndValue(VLine_HEIGHT);

    connect(m_vLineAnimation, &QPropertyAnimation::finished, [=] {
        if (!m_isWindowHide)
        {
            m_pGroupAnimation->start();
        }
        else
        {
            openMainWin();
        }
    });
}

void LoginAnimationWin::initConnections()
{
    connect(m_pLoginWindow->m_loginWindow.loginButton, &QPushButton::clicked, this, &LoginAnimationWin::onLoginButtonClicked);
    connect(m_pLoginWindow->m_loginWindow.pButtonNetSet, &QPushButton::clicked, this, &LoginAnimationWin::onNetWordSetButtonClicked);
    connect(m_pLoginWindow->m_loginWindow.pButtonMin, &QPushButton::clicked, this, &LoginAnimationWin::onMinisizeButtonClicked);
    connect(m_pLoginWindow->m_loginWindow.pButtonClose, &QPushButton::clicked, this, &LoginAnimationWin::close);
    connect(m_pLoginWindow->m_loginWindow.pButtonRegister,&QPushButton::clicked, this, &LoginAnimationWin::onRegisterButtonClicked);
    connect(m_pLoginWindow->m_loginWindow.pButtonGetPasswd,&QPushButton::clicked, this, &LoginAnimationWin::onModifyPwdButtonClicked);

    connect(m_pConfigDlg,&ConfigWin::sigConfigCancel,this,&LoginAnimationWin::onNetConfigCancel);
    connect(m_pConfigDlg,&ConfigWin::signalConfEdit,this,&LoginAnimationWin::onNetConfigOk);
    connect(m_pConfigDlg,&ConfigWin::sigMinBtnClicked, this, &LoginAnimationWin::onMinisizeButtonClicked);
    connect(m_pConfigDlg,&ConfigWin::sigClosedBtnClicked, this, &LoginAnimationWin::close);

    connect(m_pRegisterWin,&RegisterWin::sigRegisterOk,this,&LoginAnimationWin::onRegisterOk);
    connect(m_pRegisterWin,&RegisterWin::sigRegisterCancel,this,&LoginAnimationWin::onRegisterCancel);
    connect(m_pRegisterWin,&RegisterWin::sigMinBtnClicked, this, &LoginAnimationWin::onMinisizeButtonClicked);
    connect(m_pRegisterWin,&RegisterWin::sigClosedBtnClicked, this, &LoginAnimationWin::close);

    connect(m_pModifyPwdWin,&ModifyPwdWin::sigMinBtnClicked, this, &LoginAnimationWin::onMinisizeButtonClicked);
    connect(m_pModifyPwdWin,&ModifyPwdWin::sigClosedBtnClicked, this, &LoginAnimationWin::close);
    connect(m_pModifyPwdWin,&ModifyPwdWin::sigModifyOk,this,&LoginAnimationWin::onModifyOk);
    connect(m_pModifyPwdWin,&ModifyPwdWin::sigModifyCancel,this,&LoginAnimationWin::onModifyCancel);

    connect(m_pMainWin,&MainWindow::destroyed,this,&LoginAnimationWin::onMainWinDestoryed);
}

void LoginAnimationWin::initWidget()
{
    this->setWindowIcon(QIcon(":/Images/resource/flamingo.ico"));
    //窗口基本属性
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setAttribute(Qt::WA_TranslucentBackground);
    // 设置阴影边框;
    auto shadowEffect = new QGraphicsDropShadowEffect(ui.stackedWidget);
    shadowEffect->setOffset(0, 0);
    shadowEffect->setColor(Qt::black);
    shadowEffect->setBlurRadius(10);
    ui.stackedWidget->setGraphicsEffect(shadowEffect);
    //
    m_pLoginWindow = new LoginWindow;
    m_pConfigDlg = new ConfigWin;
    m_pRegisterWin = new RegisterWin;
    m_pModifyPwdWin = new ModifyPwdWin;
    ui.stackedWidget->insertWidget(0,m_pLoginWindow);
    ui.stackedWidget->insertWidget(1,m_pConfigDlg);
    ui.stackedWidget->insertWidget(2,m_pRegisterWin);
    ui.stackedWidget->insertWidget(3,m_pModifyPwdWin);
    //主窗口初始化
    m_pMainWin =MainWindow::InitInstance();
}

void LoginAnimationWin::initNetWork()
{
    m_pClientSocket->moveToThread(&m_thread);       //连同子类也移到到这个线程
    m_thread.start();

    m_pMainWin->setSocket(m_pClientSocket);

    connect(&m_thread,&QThread::finished,m_pClientSocket,&ClientSocket::deleteLater);
    connect(m_pClientSocket,&ClientSocket::signalStatus,this,&LoginAnimationWin::onTcpStatus);
    connect(this,&LoginAnimationWin::sigSend,m_pClientSocket,&ClientSocket::SltSend);
    connect(this,&LoginAnimationWin::sigConnectToHost,m_pClientSocket,&ClientSocket::ConnectToHost);
    Q_EMIT sigConnectToHost();
}

void LoginAnimationWin::Login()
{
    //检查服务器是否连接
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("Server not connected, please wait!"));
        Q_EMIT sigConnectToHost();
        return;
    }
    MyApp::m_strUserName = m_pLoginWindow->m_loginWindow.lineEditAccount->text();
    MyApp::m_strUserPwd = m_pLoginWindow->m_loginWindow.lineEditPassed->text();
    //用户密码不为空
    if(m_pLoginWindow->m_loginWindow.lineEditAccount->text().isEmpty())
    {
        CMessageBox::Infomation(tr("User name cannot be empty."));
        return;
    }else if(m_pLoginWindow->m_loginWindow.lineEditPassed->text().isEmpty())
    {
        CMessageBox::Infomation(tr("Password cannot be empty."));
        return;
    }
    //登录
    m_pLoginWindow->m_loginWindow.loginButton->setText(tr("Cancel Login"));
    m_bLogin = true;
    //Send msg...
    // 构建 Json 对象
    QJsonObject json;
    json.insert("username", m_pLoginWindow->m_loginWindow.lineEditAccount->text());
    json.insert("password", m_pLoginWindow->m_loginWindow.lineEditPassed->text());
    json.insert("clienttype", CLIENT_TYPE_PC);
    json.insert("status",STATUS_ONLINE);

    Q_EMIT sigSend(msg_type_login,json);
}

void LoginAnimationWin::loadUserCfg()
{
    //这部分代码整合到Myapp::initApp中去
    MyApp::m_strUserName = m_pLoginWindow->m_loginWindow.lineEditAccount->text();
    MyApp::m_strUserPwd = m_pLoginWindow->m_loginWindow.lineEditPassed->text();
    MyApp::m_strUserCfgFile = MyApp::m_strUsersPath + MyApp::m_strUserName + "/" + MyApp::m_strUserName + ".cfg";
    MyApp::s_strDatabasePath = MyApp::m_strUsersPath + MyApp::m_strUserName + "/ChatLog/";
    MyApp::m_strRecvPath = MyApp::m_strRecvPath + MyApp::m_strUserName + "/";
    QDir dir(MyApp::s_strDatabasePath);
    if(!dir.exists())
    {
        dir.mkdir(MyApp::s_strDatabasePath);       //FIXME:check ret?
    }

    dir.setPath(MyApp::m_strRecvPath);
    if(!dir.exists())
    {
        dir.mkpath(MyApp::m_strRecvPath);       //FIXME:check ret?
        qDebug() << MyApp::m_strRecvPath;
    }
    MyApp::m_bPlaySound = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","PlaySound",MyApp::m_bPlaySound).toBool();
    MyApp::m_bShowExitDlg = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","ShowExitDlg",MyApp::m_bPlaySound).toBool();
    MyApp::m_bMainWindowHide = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","MainWindowHide",MyApp::m_bPlaySound).toBool();
}

//打开主界面
void LoginAnimationWin::openMainWin()
{
    if(m_bLogin)
    {
        this->hide();
        QPoint point= myHelper::FormInCenter(m_pMainWin);
        QSize size(400,700);
        point = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"MainDlg","position",point).toPoint();
        size = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"MainDlg","size",size).toSize();
        m_pMainWin->move(point);
        m_pMainWin->resize(size);

        m_pMainWin->showMainWin();
    }
}

// 以下通过mousePressEvent、mouseMoveEvent、mouseReleaseEvent三个事件实现了鼠标拖动标题栏移动窗口的效果;
void LoginAnimationWin::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton && m_vLineAnimation->state() != QAbstractAnimation::Running)
	{
		m_isPressed = true;
		m_startMovePos = event->globalPos();
        m_pLoginWindow->m_pAccountListWidget->hide();
	}

	return QWidget::mousePressEvent(event);
}

void LoginAnimationWin::mouseMoveEvent(QMouseEvent *event)
{
	if (m_isPressed)
	{
		QPoint movePoint = event->globalPos() - m_startMovePos;
		QPoint widgetPos = this->pos() + movePoint;
		m_startMovePos = event->globalPos();
		this->move(widgetPos.x(), widgetPos.y());
	}
	return QWidget::mouseMoveEvent(event);
}

void LoginAnimationWin::mouseReleaseEvent(QMouseEvent *event)
{
	m_isPressed = false;
	return QWidget::mouseReleaseEvent(event);
}

void LoginAnimationWin::onLoginButtonClicked()
{
    if(!m_bLogin)
    {
        this->Login();
    }
    else
    {
        m_bLogin = false;
        m_pLoginWindow->m_loginWindow.loginButton->setText(tr("Login"));
        //取消登录以后需要重新连接信号到槽
        connect(m_pClientSocket,&ClientSocket::signalStatus,this,&LoginAnimationWin::onTcpStatus);
        Q_EMIT sigConnectToHost();
    }
}

void LoginAnimationWin::onTcpStatus(const quint8 &status)
{
    switch(status)
    {
    case ConnectedHost:{
        m_bConnected = true;
        m_pLoginWindow->m_loginWindow.LogoText->setText(tr("Dreamgo"));
    }
        break;
    case DisConnectedHost:{
        m_bConnected = false;
        m_pLoginWindow->m_loginWindow.LogoText->setText(tr("Server disconnected"));
    }
        break;
    // 登陆验证成功
    case LoginSuccess:
    {
        qDebug() << "LoginSuccess";
        disconnect(m_pClientSocket,&ClientSocket::signalStatus,this,&LoginAnimationWin::onTcpStatus);
        //加载用户设置
        loadUserCfg();

        //延迟一秒展开主界面，方便用户取消登录
        myHelper::Sleep(500);

        if(m_bLogin)
        {
            //登陆按钮关闭
            m_pLoginWindow->m_loginWindow.loginButton->setEnabled(false);
            //获取好友列表
            Q_EMIT sigSend(msg_type_getofriendlist,QJsonObject());
            //加载数据库
            DataBaseMagr::Instance()->OpenMessageDb(MyApp::s_strDatabasePath+"msg.db");
            // 开始登录完成之后的动画效果;
            ui.verticalLine->setVisible(true);
            m_vLineAnimation->setDirection(QAbstractAnimation::Forward);
            m_vLineAnimation->start();
            //保存当前登录用户信息
            bool autoLogin = m_pLoginWindow->m_loginWindow.checkBoxAutoLogin->isChecked();
            bool RememberPsw = m_pLoginWindow->m_loginWindow.checkBoxRememberPsw->isChecked();
            m_pLoginWindow->m_accountList.Modify(
                        MyApp::m_strUserName.data(),
                        MyApp::m_strUserPwd.data(),
                        0,
                        RememberPsw,
                        RememberPsw & autoLogin
                        );
            m_pLoginWindow->m_accountList.SetLastLoginUser(MyApp::m_strUserName.data());
            m_pLoginWindow->m_accountList.SaveFile(MyApp::m_strUsersFile);
        }
    }
        break;
    case LoginPasswdError:
    {
        m_bLogin = false;
        m_pLoginWindow->m_loginWindow.loginButton->setText(tr("Login"));
        CMessageBox::Infomation(tr("Login failed. Please check user name and password"));
    }
        break;
    case LoginNotRegister:
    {
        m_bLogin = false;
        m_pLoginWindow->m_loginWindow.loginButton->setText(tr("Login"));
        CMessageBox::Infomation(tr("Account not registered"));
    }
        break;
    case LoginRepeat:
    {
        m_bLogin = false;
        m_pLoginWindow->m_loginWindow.loginButton->setText(tr("Login"));
        CMessageBox::Infomation(tr("Login failed. The account is logged in"));
    }
        break;
    case RegisterOk:
    {
        CMessageBox::Infomation(tr("The account has been successfully registered.Please click login!"));
        m_pLoginWindow->m_loginWindow.lineEditAccount->setText(m_strRegPhoneNum);
        m_pLoginWindow->m_loginWindow.lineEditPassed->setText(m_strRegPassword);
    }
        break;
    case RegisterFailed:
    {
        CMessageBox::Infomation(tr("Registration failed.Please register again!"));
    }
        break;
    case RegisterAlready:
    {
        CMessageBox::Infomation("The account has been registered.");
    }
    default:
        break;
    }
}

void LoginAnimationWin::onMinisizeButtonClicked()
{
    if (Qt::Tool == (windowFlags() & Qt::Tool))
    {
        hide();
    }
    else
    {
        showMinimized();
    }
}

void LoginAnimationWin::onNetWordSetButtonClicked()
{
    ui.stackedWidget->setPage(1);
}

void LoginAnimationWin::onNetConfigOk()
{
    ui.stackedWidget->setPage(0);
    Q_EMIT sigConnectToHost();
}

void LoginAnimationWin::onNetConfigCancel()
{
    ui.stackedWidget->setPage(0);
}

void LoginAnimationWin::onRegisterButtonClicked()
{
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("Server not connected, please wait"));
        Q_EMIT sigConnectToHost();
        return;
    }
    ui.stackedWidget->setPage(2);
}

void LoginAnimationWin::onRegisterOk(const QString& phoneNbr,const QString& nickName,const QString& pwd)
{
    ui.stackedWidget->setPage(0);
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("Server not connected, please wait"));
        Q_EMIT sigConnectToHost();
        return;
    }

    m_strRegPhoneNum = phoneNbr;
    m_strRegNickName = nickName;
    m_strRegPassword = pwd;

    //Send msg...
    // 构建 Json 对象
    //{"username": "15380926632", "nickname": "沙僧", "password": "123456"}
    QJsonObject json;
    json.insert("username", m_strRegPhoneNum);
    json.insert("nickname", m_strRegNickName);
    json.insert("password", m_strRegPassword);
    //QJsonDocument jsonData(json);
    Q_EMIT sigSend(msg_type_register,json);
}

void LoginAnimationWin::onRegisterCancel()
{
    ui.stackedWidget->setPage(0);
}

void LoginAnimationWin::onModifyPwdButtonClicked()
{
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("Server not connected, please wait"));
        Q_EMIT sigConnectToHost();
        return;
    }

    ui.stackedWidget->setPage(3);
}

void LoginAnimationWin::onModifyOk(const QString &phoneNbr, const int &userid, const QString &oldpwd, const QString &newpwd)
{
    ui.stackedWidget->setPage(0);

    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("Server not connected, please wait"));
        Q_EMIT sigConnectToHost();
        return;
    }

    //Send msg...
    // 构建 Json 对象
    //{"userid": 9,"username": "xxx","oldpassword": "xxx", "newpassword": "yyy"}
    QJsonObject json;
    json.insert("username", phoneNbr);
    json.insert("userid", userid);
    json.insert("oldpassword", oldpwd);
    json.insert("newpassword", newpwd);
    //QJsonDocument jsonData(json);
    Q_EMIT sigSend(msg_type_modifypassword,json);
}

void LoginAnimationWin::onModifyCancel()
{
    ui.stackedWidget->setPage(0);
}

void LoginAnimationWin::onMainWinDestoryed()
{
    m_pMainWin = nullptr;
    this->close();
}

LoginAnimationWin::~LoginAnimationWin()
{
    m_thread.quit();
    m_thread.wait();
    if(m_pMainWin != nullptr)
    {
        disconnect(m_pMainWin,&MainWindow::destroyed,this,&LoginAnimationWin::onMainWinDestoryed);
        delete m_pMainWin;
    }
    CIULog::Unit();
    qApp->quit();
}
